use std::fmt::{Debug, Formatter};

// use std::fmt::Display;

#[derive(Debug)]
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    pub fn new () -> Post {
        Post {
            state: Some(Box::new(Draft{})),
            content: String::new(),
        }
    }
    pub fn get_state(&self) -> &Option<Box<dyn State>>{
        &self.state
    }
    pub fn add_text(&mut self, text:&str) {
        self.content.push_str(text);
    }
    pub fn content(&self) -> &str {
        // 无聊的问题： ？为啥不直接 &self.content 这个问题很无语，如果这样就不叫状态模式了，状态模式中要把状态全部封装到State中
        // 这里面 unwrap() 方法不会返回Option的None，最终肯定返回T对象，也就是 State （接口）定义的返回值。
        // 通过 unwrap() 的过滤，那么实际上返回的就是 State （对象）了，调用状态上的content() 才可以哦。
        // 另外需要注意这里使用了 as_ref 这会得到一个 Option<&Box<dny State>>
        self.state.as_ref().unwrap().content(self)
    }
    // 这个和接口 State::request_review 没有任何关系，参数定义也不一样，这就是个内部方法。
    pub fn request_review(&mut self) {
        // 题外话：为什么需要调用 self.state.take() 而不是其他的 （ *self.state，这样不行如果解引用生命周期就不对了）（self.state，这样不行不运行借用）。
        // 首先要了解一下 Option<T> 的默认值 ，它实现了 Default 接口，也就是说Option<T> 是有默认值的，默认值时None
        // take() 方法用来取出state 中Some 值的所有权，这样就可以踏踏实实的从Some(s)中取出，并在原来的位置留下None

        if let Some(s) = self.state.take() {
            // 更改state 的状态 s.request_review -> Box<dyn State>
            self.state = Some(s.request_review());
        }
    }
    pub fn approve(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.approve());
        }
    }
    pub fn reject(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.reject());
        }
    }
    pub fn edit( &mut self, new_content:&str) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.edit(self, new_content));
        }
    }
}

pub trait State {
    fn request_review(self:Box<Self>) -> Box<dyn State>;
    fn status_name(&self) -> String;
    fn approve(self:Box<Self>) -> Box<dyn State>;
    fn reject(self:Box<Self>) -> Box<dyn State>;
    // fn edit(&self, post:&mut Post,new_text:&str) {
    //
    // }
    fn edit(self:Box<Self> , post:&mut Post, new_str:&str) ->Box<dyn State>;

    // 这里涉及一个生命周期的概念要注意下，因为函数本身返回 post 参数的一部分
    // 所以要标明返回值 str 的生命周期，如下定义的生命周期长度与post 参数长度一致。
    fn content<'a> (&self, post:&'a Post) -> &'a str {
        // 这个默认的实现实际上隐藏了状态上要处理的 post.content 返回值。
        ""
    }
    // 如下方法没有定义生命周期所以会报错，可以放开试试，体会一下生命周期的作用。
    // fn content (&self, post:& Post) -> &str {
    //     // 这个默认的实现实际上隐藏了状态上要处理的 post.content 返回值。
    //     ""
    // }
}

// 给State 实现一个Debug 接口用于显示调试信息
impl Debug for dyn State {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("")
            .field(&"#########################".to_string())
            .field(&self.status_name())
            .field(&"#########################".to_string())
            .finish()
    }
}

#[derive(Debug)]
pub struct Draft {}

#[derive(Debug)]
pub struct PendingReview {}

#[derive(Debug)]
pub struct Published {}

impl State for Draft {
    // 注意这里的 self: Box<Self> 定义，而不是 self、&self、&mut self。
    // 这个语法意味着该方法只能被包裹着当前类型的Box实例调用，也就是上面 s = Box<dyn State> ，s.request_review()
    // ? 它会在调用过程中获取Box<Self>的所有权，并使旧的状态失效，从而将Post的状态值转换为一个新的状态。
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        // 返回预览的状态
        Box::new(PendingReview{} )
    }

    fn status_name(&self) -> String {
        "Draft state".to_string()
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn reject(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn edit(self:Box<Self> , post:&mut Post, new_str:&str) -> Box<dyn State> {
        post.content.clear();
        post.content.push_str(new_str);
        self
    }
}

impl State for PendingReview {
    // 对于一个已经处于审核状态的文章来说再次发起审批请求不会改变任何状态。
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn status_name(&self) -> String {
        "PendingReview state".to_string()
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        Box::new(Published {})
    }
    fn reject(self: Box<Self>) -> Box<dyn State> {
        Box::new(Draft {})
    }
    fn edit(self:Box<Self> , post:&mut Post, new_str:&str) -> Box<dyn State> {
        self
    }
}


impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn status_name(&self) -> String {
        "Published state".to_string()
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
    fn content<'a> (&self, post:&'a Post) -> &'a str {
        &post.content
    }
    fn reject(self: Box<Self>) -> Box<dyn State> {
        self
    }
    fn edit(self:Box<Self> , post:&mut Post, new_str:&str) -> Box<dyn State> {
        self
    }

    // // 没有生命周期的函数编译会报错，不信可以试试
    // fn content (&self, post:& Post) -> &str {
    //     // 这个默认的实现实际上隐藏了状态上要处理的 post.content 返回值。
    //     &post.content
    // }
}